-------------------------------------------------------------------------------
--$Date: 2008/07/31 22:51:03 $
--$RCSfile: frame_check_vhd.ejava,v $
--$Revision: 1.1.2.3 $
-------------------------------------------------------------------------------
--   ____  ____ 
--  /   /\/   / 
-- /___/  \  /    Vendor: Xilinx 
-- \   \   \/     Version : 1.5
--  \   \         Application : RocketIO GTX Wizard 
--  /   /         Filename : frame_check.vhd
-- /___/   /\     Timestamp : 
-- \   \  /  \ 
--  \___\/\___\ 
--
--
-- Module FRAME_CHECK
-- Generated by Xilinx RocketIO GTX Wizard

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;

--***********************************Entity Declaration************************

entity FRAME_CHECK is
generic
(
    RX_DATA_WIDTH            : integer := 16;
    USE_COMMA                : integer := 1;
    NONE_MSB_FIRST_DEC       : integer := 0;
    COMMA_DOUBLE_DEC         : integer := 0;
    CHANBOND_SEQ_LEN         : integer := 1;
    WORDS_IN_BRAM            : integer := 256;
    CONFIG_INDEPENDENT_LANES : integer := 0;
    START_OF_PACKET_CHAR     : std_logic_vector := x"55fb";
    COMMA_DOUBLE_CHAR        : std_logic_vector := x"f628";
    MEM_00       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_01       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_02       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_03       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_04       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_05       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_06       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_07       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_08       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_09       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0A       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0B       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0C       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0D       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0E       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_0F       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_10       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_11       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_12       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_13       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_14       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_15       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_16       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_17       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_18       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_19       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1A       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1B       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1C       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1D       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1E       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_1F       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_20       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_21       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_22       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_23       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_24       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_25       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_26       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_27       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_28       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_29       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2A       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2B       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2C       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2D       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2E       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_2F       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_30       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_31       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_32       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_33       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_34       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_35       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_36       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_37       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_38       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_39       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3A       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3B       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3C       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3D       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3E       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEM_3F       : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_00      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_01      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_02      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_03      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_04      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_05      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_06      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000";
    MEMP_07      : bit_vector :=   X"0000000000000000000000000000000000000000000000000000000000000000"
);
port
(
    -- User Interface
    RX_DATA                  : in  std_logic_vector((RX_DATA_WIDTH-1) downto 0); 
    RX_ENMCOMMA_ALIGN        : out std_logic;
    RX_ENPCOMMA_ALIGN        : out std_logic;
    RX_ENCHAN_SYNC           : out std_logic; 
    RX_CHANBOND_SEQ          : in  std_logic; 

    -- Control Interface
    INC_IN                   : in std_logic; 
    INC_OUT                  : out std_logic; 
    PATTERN_MATCH_N          : out std_logic;
    RESET_ON_ERROR           : in std_logic; 
    
    -- Error Monitoring
    ERROR_COUNT              : out std_logic_vector(7 downto 0);

    -- System Interface
    USER_CLK                 : in std_logic;       
    SYSTEM_RESET             : in std_logic
  
);

    attribute X_CORE_INFO : string;
    attribute X_CORE_INFO of FRAME_CHECK : entity is "gtxwizard_v1_5, Coregen v10.1_ip3";

end FRAME_CHECK;


architecture RTL of FRAME_CHECK is


--***********************************Parameter Declarations********************

    constant DLY : time := 1 ns;

--***************************Internal Register Declarations********************

    signal  begin_r                     :   std_logic;
    signal  data_error_detected_r       :   std_logic;
    signal  error_count_r               :   unsigned(8 downto 0);
    signal  error_detected_r            :   std_logic;
    signal  read_counter_i              :   unsigned(8 downto 0);    
    signal  rx_chanbond_seq_r           :   std_logic;
    signal  rx_chanbond_seq_r2          :   std_logic;
    signal  rx_chanbond_seq_r3          :   std_logic;
    signal  rx_data_r                   :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r2                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r3                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r4                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r5                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r6                  :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_r_track             :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  start_of_packet_detected_r  :   std_logic;    
    signal  track_data_r                :   std_logic;
    signal  track_data_r2               :   std_logic;
    signal  track_data_r3               :   std_logic;
    signal  sel                         :   std_logic_vector(1 downto 0);
    
 
--*********************************Wire Declarations***************************
   
    signal  bram_data_r                 :   std_logic_vector(31 downto 0);
    signal  chanbondseq_in_data         :   std_logic;
    signal  error_detected_c            :   std_logic;
    signal  input_to_chanbond_data_i    :   std_logic;
    signal  input_to_chanbond_reg_i     :   std_logic;
    signal  next_begin_c                :   std_logic;
    signal  next_data_error_detected_c  :   std_logic;
    signal  next_track_data_c           :   std_logic;
    signal  start_of_packet_detected_c  :   std_logic;
    signal  rx_chanbond_reg             :   std_logic_vector((CHANBOND_SEQ_LEN-1) downto 0);
    signal  rx_chanbond_reg_bitwise_or_i:   std_logic;
    signal  rx_data_aligned             :   std_logic_vector((RX_DATA_WIDTH-1) downto 0);
    signal  rx_data_has_start_char_c    :   std_logic;
    signal  rx_data_matches_bram_c      :   std_logic;
    signal  tied_to_ground_i            :   std_logic;
    signal  tied_to_ground_vec_i        :   std_logic_vector(31 downto 0);
    signal  tied_to_vcc_i               :   std_logic;


--*********************************Main Body of Code***************************
begin

    --_______________________  Static signal Assigments _______________________   

    tied_to_ground_i        <= '0';
    tied_to_ground_vec_i    <= (others=>'0');
    tied_to_vcc_i           <= '1';

    --______________________ Register RXDATA once to ease timing ______________   

    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            rx_data_r <= RX_DATA after DLY;
        end if;
    end process;

    --________________________________ State machine __________________________    
    
    
    -- State registers
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(RESET_ON_ERROR ='1' or SYSTEM_RESET = '1') then
                begin_r                <=  '1' after DLY;
                track_data_r           <=  '0' after DLY;
                data_error_detected_r  <=  '0' after DLY;
            else
                begin_r                <=  next_begin_c after DLY;
                track_data_r           <=  next_track_data_c after DLY;
                data_error_detected_r  <=  next_data_error_detected_c after DLY;
            end if;
        end if;
    end process;

    -- Next state logic
    next_begin_c               <=   (begin_r and not start_of_packet_detected_r) or data_error_detected_r ;

    next_track_data_c          <=   (begin_r and start_of_packet_detected_r) or (track_data_r and not error_detected_r);
                                      
    next_data_error_detected_c <=   (track_data_r and error_detected_r);                               
        
    start_of_packet_detected_c <=   INC_IN when (CONFIG_INDEPENDENT_LANES=0) else rx_data_has_start_char_c;

    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        start_of_packet_detected_r    <=   start_of_packet_detected_c after DLY;
    end if;    
    end process;
    
    -- Registering for timing
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        track_data_r2    <=   track_data_r after DLY;
    end if;    
    end process;

    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        track_data_r3    <=   track_data_r2 after DLY;
    end if;    
    end process;

    --______________________________ Capture incoming data ____________________    

datapath_width_32_or_40: if ((RX_DATA_WIDTH=32) or (RX_DATA_WIDTH=40)) generate 
    -- Comma realignment logic might be needed. 4 levels of registering for RXDATA to meet timing
    -- In 4 Byte scenario, when align_comma_word=2, Comma can appear on any of the three lower bytes
    -- { BYTE3 | BYTE2 | BYTE1 | BYTE0 } - Comma can appear on BYTE0/1/2
    -- If Comma appears on BYTE1/2, RX_DATA is realigned so that Comma appears on BYTE0 in rx_data_r_track

not_comma_double: if (COMMA_DOUBLE_DEC=0) generate
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if((RESET_ON_ERROR='1') or (SYSTEM_RESET='1')) then 
                sel <= "00";
            elsif ((begin_r= '1') and ((rx_chanbond_seq_r = '0') and (rx_chanbond_seq_r2 = '0'))) then
            -- if Comma appears on BYTE3 ..
                if(rx_data_r((RX_DATA_WIDTH - 1) downto (3*RX_DATA_WIDTH/4)) = START_OF_PACKET_CHAR) then
                    sel <= "11";
                elsif(rx_data_r((RX_DATA_WIDTH/2-1) downto RX_DATA_WIDTH/4) = START_OF_PACKET_CHAR) then
                    sel <= "10";
                -- if Comma appears on BYTE1
                elsif(rx_data_r((3*RX_DATA_WIDTH/4 - 1) downto RX_DATA_WIDTH/2) = START_OF_PACKET_CHAR) then
                    sel <= "01";
                elsif(rx_data_r((RX_DATA_WIDTH/4 - 1) downto 0) = START_OF_PACKET_CHAR) then
                    sel <= "00";
                end if;
            end if;
        end if;
    end process;
end generate not_comma_double;

comma_double: if (COMMA_DOUBLE_DEC=1) generate
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if((RESET_ON_ERROR='1') or (SYSTEM_RESET='1')) then 
                sel <= "00";
            elsif ((begin_r= '1') and ((rx_chanbond_seq_r = '0') and (rx_chanbond_seq_r2 = '0') and (rx_chanbond_seq_r3 = '0'))) then
            -- if Comma appears on BYTE2 ..
                if(rx_data_r((RX_DATA_WIDTH/2 - 1) downto 0) = COMMA_DOUBLE_CHAR) then
                    sel <= "00";
                elsif(rx_data_r((RX_DATA_WIDTH-1) downto RX_DATA_WIDTH/2) = COMMA_DOUBLE_CHAR) then
                    sel <= "01";
                end if;
            end if;
        end if;
    end process;
end generate comma_double;

none_msbfirst_decoding: if (NONE_MSB_FIRST_DEC=1) generate 
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(SYSTEM_RESET = '1') then 
                rx_data_r3      <=  (others => '0') after DLY;
            else
                if(sel = "10")  then
                    rx_data_r3  <=  rx_data_r2((RX_DATA_WIDTH/4 -1) downto 0) & rx_data_r((RX_DATA_WIDTH - 1) downto RX_DATA_WIDTH/4) after DLY;  
                elsif(sel = "01") then  
                    rx_data_r3  <=  rx_data_r2((RX_DATA_WIDTH/2 -1) downto 0) & rx_data_r((RX_DATA_WIDTH - 1) downto RX_DATA_WIDTH/2) after DLY;  
                elsif(sel = "11") then  
                    rx_data_r3  <=  rx_data_r2((3*RX_DATA_WIDTH/4 - 1) downto 0) & rx_data_r((RX_DATA_WIDTH-1) downto 3*RX_DATA_WIDTH/4) after DLY;  
                else              
                    rx_data_r3  <=  rx_data_r2 after DLY;
                end if;    
            end if; 
        end if;
    end process;
end generate none_msbfirst_decoding;

not_none_msbfirst_decoding: if (NONE_MSB_FIRST_DEC=0) generate 
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(SYSTEM_RESET = '1') then 
                rx_data_r3      <=  (others => '0') after DLY;
            else
                if(sel = "10")  then
                    rx_data_r3  <=  rx_data_r((RX_DATA_WIDTH/4 - 1) downto 0) & rx_data_r2((RX_DATA_WIDTH-1) downto RX_DATA_WIDTH/4) after DLY;  
                elsif(sel = "01") then  
                    rx_data_r3  <=  rx_data_r((RX_DATA_WIDTH/2 -1) downto 0) & rx_data_r2((RX_DATA_WIDTH - 1) downto RX_DATA_WIDTH/2) after DLY;  
                elsif(sel = "11") then  
                    rx_data_r3  <=  rx_data_r((3*RX_DATA_WIDTH/4 -1) downto 0) & rx_data_r2((RX_DATA_WIDTH - 1) downto 3*RX_DATA_WIDTH/4) after DLY;  
                else              
                    rx_data_r3  <=  rx_data_r2 after DLY;
                end if;    
            end if; 
        end if;
    end process;
end generate not_none_msbfirst_decoding;
end generate datapath_width_32_or_40;

datapath_width_16_or_20: if ((RX_DATA_WIDTH=16) or (RX_DATA_WIDTH=20)) generate
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if((RESET_ON_ERROR='1') or (SYSTEM_RESET='1')) then 
                sel <= "00";
            elsif ((begin_r= '1') and ((rx_chanbond_seq_r = '0') and (rx_chanbond_seq_r2 = '0') and (rx_chanbond_seq_r3 = '0'))) then
            -- if Comma appears on BYTE2 ..
                if(rx_data_r((RX_DATA_WIDTH/2 - 1) downto 0) = START_OF_PACKET_CHAR) then
                    sel <= "00";
                elsif(rx_data_r((RX_DATA_WIDTH-1) downto RX_DATA_WIDTH/2) = START_OF_PACKET_CHAR) then
                    sel <= "01";
                end if;
            end if;
        end if;
    end process;

none_msbfirst_decoding: if (NONE_MSB_FIRST_DEC=1) generate 
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(SYSTEM_RESET = '1') then 
                rx_data_r3      <=  (others => '0') after DLY;
            else
                if(sel = "01")  then
                    rx_data_r3  <=  rx_data_r2((RX_DATA_WIDTH/2 - 1) downto 0) & rx_data_r((RX_DATA_WIDTH-1) downto RX_DATA_WIDTH/2) after DLY;  
                else              
                    rx_data_r3  <=  rx_data_r2 after DLY;
                end if;    
            end if; 
        end if;
    end process;
end generate none_msbfirst_decoding;

not_none_msbfirst_decoding: if (NONE_MSB_FIRST_DEC=0) generate 
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(SYSTEM_RESET = '1') then 
                rx_data_r3      <=  (others => '0') after DLY;
            else
                if(sel = "01")  then
                    rx_data_r3  <=  rx_data_r((RX_DATA_WIDTH/2 - 1) downto 0) & rx_data_r2((RX_DATA_WIDTH-1) downto RX_DATA_WIDTH/2) after DLY;  
                else              
                    rx_data_r3  <=  rx_data_r2 after DLY;
                end if;    
            end if; 
        end if;
    end process;
end generate not_none_msbfirst_decoding;
end generate datapath_width_16_or_20;

datapath_width_32_40_16_or_20: if ((RX_DATA_WIDTH=16) or (RX_DATA_WIDTH=20) or (RX_DATA_WIDTH=32) or (RX_DATA_WIDTH=40)) generate
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(SYSTEM_RESET = '1') then 
                rx_data_r2      <=  (others => '0') after DLY;
                rx_data_r4      <=  (others => '0') after DLY;
                rx_data_r5      <=  (others => '0') after DLY;
                rx_data_r_track <=  (others => '0') after DLY;
            else
                rx_data_r2      <=  rx_data_r after DLY;
                rx_data_r4      <=  rx_data_r3 after DLY;
                rx_data_r5      <=  rx_data_r4 after DLY;
                rx_data_r6      <=  rx_data_r5 after DLY;
                rx_data_r_track <=  rx_data_r6 after DLY;
            end if;
        end if;    
    end process;

    rx_data_aligned <= rx_data_r3;

    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            rx_chanbond_seq_r    <=  RX_CHANBOND_SEQ after DLY;
            rx_chanbond_seq_r2   <=  rx_chanbond_seq_r after DLY;
            rx_chanbond_seq_r3   <=  rx_chanbond_seq_r2 after DLY;
        end if;    
    end process;

    input_to_chanbond_reg_i  <= rx_chanbond_seq_r2;
    input_to_chanbond_data_i <= tied_to_ground_i;

end generate datapath_width_32_40_16_or_20;

datapath_width_8_or_10: if ((RX_DATA_WIDTH=8) or (RX_DATA_WIDTH=10)) generate
    process( USER_CLK )
    begin
        if(USER_CLK'event and USER_CLK = '1') then
            if(SYSTEM_RESET = '1') then 
                rx_data_r2      <=  (others => '0') after DLY;
                rx_data_r3      <=  (others => '0') after DLY;
                rx_data_r4      <=  (others => '0') after DLY;
                rx_data_r_track <=  (others => '0') after DLY;
            else
                rx_data_r2      <=  rx_data_r after DLY;
                rx_data_r3      <=  rx_data_r2 after DLY;
                rx_data_r4      <=  rx_data_r3 after DLY;
                rx_data_r_track <=  rx_data_r4 after DLY;
            end if;
        end if;    
    end process;
    
    rx_data_aligned <= RX_DATA;
    input_to_chanbond_reg_i  <= RX_CHANBOND_SEQ;
    input_to_chanbond_data_i <= RX_CHANBOND_SEQ;
end generate datapath_width_8_or_10;

    --___________________________ Code for Channel bonding ____________________    
    -- code to prevent checking of clock correction sequences for the start of packet char
    register_chan_seq: for i in 0 to (CHANBOND_SEQ_LEN-1) generate
        case_i_equal_to_0: if (i=0) generate 
            rx_chanbond_reg_0 : FD port map (Q => rx_chanbond_reg(i),D => input_to_chanbond_reg_i,C => USER_CLK);
        end generate case_i_equal_to_0;
        case_i_greater_than_0: if (i>0) generate 
            rx_chanbond_reg_i :FD port map (Q => rx_chanbond_reg(i),D => rx_chanbond_reg(i-1),C => USER_CLK);
        end generate case_i_greater_than_0;
    end generate register_chan_seq;
    
    chanbondseq_in_data <= input_to_chanbond_data_i or rx_chanbond_reg_bitwise_or_i;

    process(rx_chanbond_reg)
    variable rx_chanbond_var : std_logic;
    variable i               : std_logic;
    begin
        rx_chanbond_var := '0';
        bit_wise_or : for  i in 0 to (CHANBOND_SEQ_LEN-1) loop
            rx_chanbond_var :=  rx_chanbond_var or rx_chanbond_reg(i);
        end loop;
        rx_chanbond_reg_bitwise_or_i <= rx_chanbond_var;
    end process;


comma_double_decoding_and_32_16 : if (((RX_DATA_WIDTH=32) or (RX_DATA_WIDTH=16)) and (COMMA_DOUBLE_DEC=1)) generate
    rx_data_has_start_char_c <= '1' when ((rx_data_aligned(15 downto 0) = COMMA_DOUBLE_CHAR) and (chanbondseq_in_data='0')) else '0';
 end generate comma_double_decoding_and_32_16;

not_comma_double_and_32_16_or_8 : if ((((RX_DATA_WIDTH=32) or (RX_DATA_WIDTH=16)) and (COMMA_DOUBLE_DEC=0)) or (RX_DATA_WIDTH=8)) generate
    rx_data_has_start_char_c <= '1' when ((rx_data_aligned(7 downto 0) = START_OF_PACKET_CHAR) and (chanbondseq_in_data='0')) else '0';
 end generate not_comma_double_and_32_16_or_8;

comma_double_decoding_and_40_or_20 : if (((RX_DATA_WIDTH=40) or (RX_DATA_WIDTH=20)) and (COMMA_DOUBLE_DEC=1)) generate
    rx_data_has_start_char_c <= '1' when ((rx_data_aligned(19 downto 0) = COMMA_DOUBLE_CHAR) and (chanbondseq_in_data='0')) else '0';
 end generate comma_double_decoding_and_40_or_20;

not_comma_double_and_40_20_or_10 : if ((((RX_DATA_WIDTH=40) or (RX_DATA_WIDTH=20)) and (COMMA_DOUBLE_DEC=0)) or (RX_DATA_WIDTH=10)) generate
    rx_data_has_start_char_c <= '1' when ((rx_data_aligned(9 downto 0) = START_OF_PACKET_CHAR) and (chanbondseq_in_data='0')) else '0';
 end generate not_comma_double_and_40_20_or_10;

    --_____________________________ Assign output ports _______________________    

    INC_OUT         <=  start_of_packet_detected_c;   

    PATTERN_MATCH_N <=  data_error_detected_r;   

    -- Drive the enamcommaalign port of the mgt for alignment
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if(SYSTEM_RESET = '1') then 
            RX_ENMCOMMA_ALIGN   <= '0' after DLY;
        else              
            RX_ENMCOMMA_ALIGN   <= '1' after DLY;
        end if;
    end if;    
    end process;

    -- Drive the enapcommaalign port of the mgt for alignment
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if(SYSTEM_RESET = '1') then  
            RX_ENPCOMMA_ALIGN   <= '0' after DLY;
        else              
            RX_ENPCOMMA_ALIGN   <= '1' after DLY;
        end if;
    end if;    
    end process;

    -- Drive the enchansync port of the mgt for channel bonding
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if(SYSTEM_RESET = '1') then 
            RX_ENCHAN_SYNC   <= '0' after DLY;
        else              
            RX_ENCHAN_SYNC   <= '1' after DLY;
        end if;
    end if;    
    end process;

    
    --___________________________ Check incoming data for errors ______________
         
    
    --An error is detected when data read for the BRAM does not match the incoming data
use_40bit : if RX_DATA_WIDTH = 40 generate
    rx_data_matches_bram_c <= '0' when (rx_data_r_track /= (tied_to_ground_vec_i(7 downto 0) & bram_data_r)) else '1';
end generate use_40bit;

not_40bit : if RX_DATA_WIDTH /= 40 generate
    rx_data_matches_bram_c <= '0' when (rx_data_r_track /= bram_data_r((RX_DATA_WIDTH-1) downto 0)) else '1';
end generate not_40bit;

    error_detected_c    <=   track_data_r3 and not rx_data_matches_bram_c;   
    
    
enable_error_check : if USE_COMMA = 1 generate
    --We register the error_detected signal for use with the error counter logic
    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if(not(track_data_r = '1')) then 
            error_detected_r    <= '0' after DLY;
        else
            error_detected_r    <=  error_detected_c after DLY;
        end if;
    end if;    
    end process;
end generate enable_error_check;

disable_error_check : if USE_COMMA = 0 generate
    -- Since the comma detect logic has not been enabled, the error counter has been disabled since
    -- it doesnt make sense to be searching for an align character in the data. To enable the error 
    -- count again, please see the code above
    
       error_detected_r    <= '0';

end generate disable_error_check;

    
    --We count the total number of errors we detect. By keeping a count we make it less likely that we will miss
    --errors we did not directly observe. This counter must be reset when it reaches its max value
    process ( USER_CLK )
    begin
    if( USER_CLK'event and USER_CLK = '1') then
        if(SYSTEM_RESET='1') then
            error_count_r       <=  (others => '0') after DLY;
        elsif(error_detected_r = '1') then
            error_count_r       <=  error_count_r + 1 after DLY;
        end if;
    end if;
    end process;
        
            
    --Here we connect the lower 8 bits of the count (the MSbit is used only to check when the counter reaches
    --max value) to the module output
    ERROR_COUNT     <=   std_logic_vector(error_count_r(7 downto 0));

    --____________________________ Counter to read from BRAM __________________________    

    process( USER_CLK )
    begin
    if(USER_CLK'event and USER_CLK = '1') then
        if((SYSTEM_RESET='1') or (read_counter_i = (WORDS_IN_BRAM-1)) 
        or ((start_of_packet_detected_r and not track_data_r)='1'))  then
            read_counter_i   <=  (others => '0') after DLY;
        else read_counter_i  <=  read_counter_i + 1 after DLY;
        end if;
    end if;
    end process;

    --________________________________ BRAM Instantiation _____________________________    

    dual_port_block_ram_i  :  RAMB16_S36_S36 
    generic map
    (
        INIT_00          =>  MEM_00,
        INIT_01          =>  MEM_01,
        INIT_02          =>  MEM_02,
        INIT_03          =>  MEM_03,
        INIT_04          =>  MEM_04,
        INIT_05          =>  MEM_05,
        INIT_06          =>  MEM_06,
        INIT_07          =>  MEM_07,
        INIT_08          =>  MEM_08,
        INIT_09          =>  MEM_09,
        INIT_0A          =>  MEM_0A,
        INIT_0B          =>  MEM_0B,
        INIT_0C          =>  MEM_0C,
        INIT_0D          =>  MEM_0D,
        INIT_0E          =>  MEM_0E,
        INIT_0F          =>  MEM_0F,
        INIT_10          =>  MEM_10,
        INIT_11          =>  MEM_11,
        INIT_12          =>  MEM_12,
        INIT_13          =>  MEM_13,
        INIT_14          =>  MEM_14,
        INIT_15          =>  MEM_15,
        INIT_16          =>  MEM_16,
        INIT_17          =>  MEM_17,
        INIT_18          =>  MEM_18,
        INIT_19          =>  MEM_19,
        INIT_1A          =>  MEM_1A,
        INIT_1B          =>  MEM_1B,
        INIT_1C          =>  MEM_1C,
        INIT_1D          =>  MEM_1D,
        INIT_1E          =>  MEM_1E,
        INIT_1F          =>  MEM_1F,
        INIT_20          =>  MEM_20,
        INIT_21          =>  MEM_21,
        INIT_22          =>  MEM_22,
        INIT_23          =>  MEM_23,
        INIT_24          =>  MEM_24,
        INIT_25          =>  MEM_25,
        INIT_26          =>  MEM_26,
        INIT_27          =>  MEM_27,
        INIT_28          =>  MEM_28,
        INIT_29          =>  MEM_29,
        INIT_2A          =>  MEM_2A,
        INIT_2B          =>  MEM_2B,
        INIT_2C          =>  MEM_2C,
        INIT_2D          =>  MEM_2D,
        INIT_2E          =>  MEM_2E,
        INIT_2F          =>  MEM_2F,
        INIT_30          =>  MEM_30,
        INIT_31          =>  MEM_31,
        INIT_32          =>  MEM_32,
        INIT_33          =>  MEM_33,
        INIT_34          =>  MEM_34,
        INIT_35          =>  MEM_35,
        INIT_36          =>  MEM_36,
        INIT_37          =>  MEM_37,
        INIT_38          =>  MEM_38,
        INIT_39          =>  MEM_39,
        INIT_3A          =>  MEM_3A,
        INIT_3B          =>  MEM_3B,
        INIT_3C          =>  MEM_3C,
        INIT_3D          =>  MEM_3D,
        INIT_3E          =>  MEM_3E,
        INIT_3F          =>  MEM_3F,
        INITP_00         =>  MEMP_00,
        INITP_01         =>  MEMP_01,
        INITP_02         =>  MEMP_02,
        INITP_03         =>  MEMP_03,
        INITP_04         =>  MEMP_04,
        INITP_05         =>  MEMP_05,
        INITP_06         =>  MEMP_06,
        INITP_07         =>  MEMP_07

    )
    port map 
    (
        ADDRA            =>  std_logic_vector(read_counter_i),
        DIA              =>  tied_to_ground_vec_i(31 downto 0),
        DIPA             =>  tied_to_ground_vec_i(3 downto 0),
        DOA              =>  bram_data_r,
        DOPA             =>  open, 
        WEA              =>  tied_to_ground_i,
        ENA              =>  tied_to_vcc_i,
        SSRA             =>  tied_to_ground_i, 
        CLKA             =>  USER_CLK,
                  
        ADDRB            =>  tied_to_ground_vec_i(8 downto 0),
        DIB              =>  tied_to_ground_vec_i(31 downto 0),
        DIPB             =>  tied_to_ground_vec_i(3 downto 0),
        DOB              =>  open,  
        DOPB             =>  open, 
        WEB              =>  tied_to_ground_i,
        ENB              =>  tied_to_ground_i,
        SSRB             =>  tied_to_ground_i,
        CLKB             =>  tied_to_ground_i       
    );       
    
    
end RTL;           

